{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import pymongo\n",
    "from pymongo import MongoClient\n",
    "import requests\n",
    "from requests import ReadTimeout\n",
    "from pprint import pprint\n",
    "from mxnet.image import imread\n",
    "from mxnet import nd\n",
    "import numpy as np\n",
    "from io import BytesIO\n",
    "from PIL import Image\n",
    "import asyncio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "host =  \"api/v1/\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Mongo table list:\n",
      " ['jmd_test_xb', 'word_dict', 'wangyiwen_test', 'image_faiss_dual_taobao', 'test_w2v2', 'test_w2v3', 'w2v_test_xb2', 'car_sim', 'wordvector_index', 'tutorial_test', 'image_metric_taobao128', 'sku_img_embedding', 'dengjuntest', 'test_w2v', 'test_w2v1', 'image_faiss_dual', 'w2v_test_xb', 'nnparamtest', 'image_faiss_dual_tmall', 'image_nn_prod', 'image_faiss_prod', 'w2v_total', 'car_intro_embedding', 'image_faiss_prod2', 'image_nn_test', 'w2v_formal']\n",
      "Faiss index list:\n",
      " ['jmd_test_xb', 'wangyiwen_test', 'image_faiss_dual_taobao', 'test_w2v3', 'w2v_test_xb2', 'car_sim', 'wordvector_index', 'tutorial_test', 'sku_img_embedding', 'test_w2v', 'image_faiss_dual', 'w2v_test_xb', 'nnparamtest', 'image_faiss_dual_tmall', 'image_nn_prod', 'image_faiss_prod', 'w2v_total', 'car_intro_embedding', 'image_faiss_prod2', 'image_nn_test']\n"
     ]
    }
   ],
   "source": [
    "try:\n",
    "    ret = requests.get(host + \"manage/models/list\",timeout=1)\n",
    "    print(\"Mongo table list:\\n\",ret.json())\n",
    "except ReadTimeout:\n",
    "    pprint(\"list table time out\")\n",
    "try:\n",
    "    ret = requests.get(host + \"manage/models/loaded\")\n",
    "    print(\"Faiss index list:\\n\",ret.json())\n",
    "except ReadTimeout:\n",
    "    print(\"list index time out\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 96,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "index_name = 'image_metric_taobao128'\n",
    "status = requests.post(host + 'model/{0}/'.format(index_name) +\"status\").json()['info']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 98,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'config': {'compression': {'m': 64},\n",
      "            'dim': 128,\n",
      "            'history': [{'data_size': 0,\n",
      "                         'operation': 'Initialized',\n",
      "                         'time': '2018-08-09 15:21:17'}],\n",
      "            'index_name': 'image_metric_taobao128',\n",
      "            'metric': 'l2'},\n",
      " 'faiss_index': {'ntotal': 0},\n",
      " 'saved': True,\n",
      " 'table': {'data_size': 28259}}\n"
     ]
    }
   ],
   "source": [
    "pprint(status)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 99,
   "metadata": {},
   "outputs": [
    {
     "ename": "JSONDecodeError",
     "evalue": "Expecting value: line 1 column 1 (char 0)",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mJSONDecodeError\u001b[0m                           Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-99-ff31f2d59021>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mstatus\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mrequests\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mpost\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhost\u001b[0m \u001b[1;33m+\u001b[0m \u001b[1;34m'model/{0}/'\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mindex_name\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;33m+\u001b[0m\u001b[1;34m\"build\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mjson\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m[\u001b[0m\u001b[1;34m'info'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32mc:\\program files\\python36\\lib\\site-packages\\requests\\models.py\u001b[0m in \u001b[0;36mjson\u001b[1;34m(self, **kwargs)\u001b[0m\n\u001b[0;32m    894\u001b[0m                     \u001b[1;31m# used.\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    895\u001b[0m                     \u001b[1;32mpass\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 896\u001b[1;33m         \u001b[1;32mreturn\u001b[0m \u001b[0mcomplexjson\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mloads\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mtext\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;33m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    897\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    898\u001b[0m     \u001b[1;33m@\u001b[0m\u001b[0mproperty\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mc:\\program files\\python36\\lib\\json\\__init__.py\u001b[0m in \u001b[0;36mloads\u001b[1;34m(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)\u001b[0m\n\u001b[0;32m    352\u001b[0m             \u001b[0mparse_int\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m \u001b[1;32mand\u001b[0m \u001b[0mparse_float\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m \u001b[1;32mand\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    353\u001b[0m             parse_constant is None and object_pairs_hook is None and not kw):\n\u001b[1;32m--> 354\u001b[1;33m         \u001b[1;32mreturn\u001b[0m \u001b[0m_default_decoder\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdecode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    355\u001b[0m     \u001b[1;32mif\u001b[0m \u001b[0mcls\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    356\u001b[0m         \u001b[0mcls\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mJSONDecoder\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mc:\\program files\\python36\\lib\\json\\decoder.py\u001b[0m in \u001b[0;36mdecode\u001b[1;34m(self, s, _w)\u001b[0m\n\u001b[0;32m    337\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    338\u001b[0m         \"\"\"\n\u001b[1;32m--> 339\u001b[1;33m         \u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mraw_decode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0midx\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0m_w\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m0\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    340\u001b[0m         \u001b[0mend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0m_w\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mend\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    341\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mend\u001b[0m \u001b[1;33m!=\u001b[0m \u001b[0mlen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mc:\\program files\\python36\\lib\\json\\decoder.py\u001b[0m in \u001b[0;36mraw_decode\u001b[1;34m(self, s, idx)\u001b[0m\n\u001b[0;32m    355\u001b[0m             \u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mscan_once\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0ms\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0midx\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    356\u001b[0m         \u001b[1;32mexcept\u001b[0m \u001b[0mStopIteration\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 357\u001b[1;33m             \u001b[1;32mraise\u001b[0m \u001b[0mJSONDecodeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Expecting value\"\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0ms\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0merr\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvalue\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfrom\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    358\u001b[0m         \u001b[1;32mreturn\u001b[0m \u001b[0mobj\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mend\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mJSONDecodeError\u001b[0m: Expecting value: line 1 column 1 (char 0)"
     ]
    }
   ],
   "source": [
    "status = requests.post(host + 'model/{0}/'.format(index_name) +\"build\").json()['info']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 100,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'config': {'index_name': 'image_metric_taobao128',\n",
       "  'metric': 'l2',\n",
       "  'compression': {'m': 64},\n",
       "  'history': [{'time': '2018-08-09 15:21:17',\n",
       "    'operation': 'Initialized',\n",
       "    'data_size': 0}],\n",
       "  'dim': 128},\n",
       " 'table': {'data_size': 28259},\n",
       " 'faiss_index': {'ntotal': 0},\n",
       " 'saved': True}"
      ]
     },
     "execution_count": 100,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "status"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "index_name = 'image_nn_prod'\n",
    "status = requests.post(host + 'model/{0}/'.format(index_name) +\"status\").json()['info']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "{'config': {'index_name': 'image_nn_prod',\n",
       "  'training_size': 262144,\n",
       "  'metric': 'l2',\n",
       "  'history': [{'time': '2018-01-12 14:57:06',\n",
       "    'operation': 'Training',\n",
       "    'data_size': 301317},\n",
       "   {'time': '2018-01-12 15:15:12',\n",
       "    'operation': 'Trained',\n",
       "    'data_size': 301317},\n",
       "   {'time': '2018-01-16 18:05:39', 'operation': 'Saved', 'data_size': 301317},\n",
       "   {'time': '2018-01-17 21:47:06', 'operation': 'Saved', 'data_size': 301317},\n",
       "   {'time': '2018-01-22 09:59:20', 'operation': 'Saved', 'data_size': 301317}],\n",
       "  'dim': 4096,\n",
       "  'use_gpu': False,\n",
       "  'nprobe': 20,\n",
       "  'nlist': 65536,\n",
       "  'compression': {'M_mi': 2, 'nbit_mi': 8, 'm': 1024, 'nbit': 8}},\n",
       " 'table': {'data_size': 301317},\n",
       " 'faiss_index': {'nprobe': 5,\n",
       "  'ntotal': 301317,\n",
       "  'check': False,\n",
       "  'id_set': 301317},\n",
       " 'saved': True}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "status"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "dim = 128 #向量的维度,LeNet的输出前一层是1024,AlexNet或者VggNet的全连接层多为2048\n",
    "m=64 #参考选择列表[{\"dim\":2048,\"m\":256},{\"dim\":1024\",\"m\":128},{\"dim\":2048,\"m\":128},{\"dim\":1024,\"m\":64}]\n",
    "model = 'image_metric_taobao128'\n",
    "nnindex = {\"dim\":dim,'metric':'cosine','compression':{'m':m},'index_name':model}\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "path = 'model/'+model+'/'\n",
    "ret = requests.post(host + path +\"create\",json={'nnindex':nnindex})\n",
    "print(\"create index result\",ret.json())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 60,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from pymongo import MongoClient\n",
    "mongdb={}\n",
    "#mongodb://.mongodb.rds.aliyuncs.com:3717,dds-bp10da4305cf39f41.mongodb.rds.aliyuncs.com:3717/admin?replicaSet=mgset-5028117\n",
    "mongdb['host']='dds-bp10da4305cf39f42.mongodb.rds.aliyuncs.com'\n",
    "mongdb['port']=3717\n",
    "client=MongoClient(host=mongdb['host'],port=mongdb['port'])\n",
    "dev=client.get_database('dev')\n",
    "dev.authenticate(name='',password='123')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\program files\\python36\\lib\\site-packages\\ipykernel_launcher.py:1: DeprecationWarning: collection_names is deprecated. Use list_collection_names instead.\n",
      "  \"\"\"Entry point for launching an IPython kernel.\n"
     ]
    }
   ],
   "source": [
    "collection_list = [name for name in dev.collection_names() if not name.endswith('config')]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "301317\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\program files\\python36\\lib\\site-packages\\ipykernel_launcher.py:2: DeprecationWarning: count is deprecated. Use estimated_document_count or count_documents instead. Please note that $where must be replaced by $expr, $near must be replaced by $geoWithin with $center, and $nearSphere must be replaced by $geoWithin with $centerSphere\n",
      "  \n"
     ]
    }
   ],
   "source": [
    "nn_prod = dev.get_collection('image_nn_prod')\n",
    "print(nn_prod.count())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "c:\\program files\\python36\\lib\\site-packages\\ipykernel_launcher.py:2: DeprecationWarning: count is deprecated. Use estimated_document_count or count_documents instead. Please note that $where must be replaced by $expr, $near must be replaced by $geoWithin with $center, and $nearSphere must be replaced by $geoWithin with $centerSphere\n",
      "  \n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "28259"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "image_nn = dev.get_collection('image_metric_taobao128')\n",
    "image_nn.count()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "cursor = image_nn.find()\n",
    "for item in cursor:\n",
    "    #pprint(item)\n",
    "    #image_nn.delete_one({'_id':item['_id']})\n",
    "    #break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "{'_id': 'ImageItem/instagram/f2bc9a0ab6c16e8223e9717efc90c347_0',\n",
      " '_index': 'image_metric_taobao128',\n",
      " '_source': {'_int_id': 14460861856687057,\n",
      "             'authorid': '186901415',\n",
      "             'authorname': 'victoriabeckham',\n",
      "             'body_parsed': '[{\"type\": \"img\", \"value\": '\n",
      "                            '\"images/instagram/f2bc9a0ab6c16e8223e9717efc90c347\"}]',\n",
      "             'cdn_url': 'https://cdn.aidigger.com/images/instagram/f2bc9a0ab6c16e8223e9717efc90c347.jpeg',\n",
      "             'commentcount': '1133',\n",
      "             'headline': 'I am overwhelmed by your response to the launch of '\n",
      "                         'my #VBxTarget collaboration! Thank you so much for '\n",
      "                         'your patience and sorry for any frustration for '\n",
      "                         'those shopping on victoriabeckham.com. Hold tight! x '\n",
      "                         'VB',\n",
      "             'height': '803',\n",
      "             'id': None,\n",
      "             'like': '100456',\n",
      "             'pic_url': 'https://www.instagram.com/p/BSrHRbmhsoH/?taken-by=victoriabeckham',\n",
      "             'picid': 'ImageItem/instagram/f2bc9a0ab6c16e8223e9717efc90c347',\n",
      "             'pubdate': '2017-04-10 01:52:14',\n",
      "             'shortcode': 'BSrHRbmhsoH',\n",
      "             'size': '867240',\n",
      "             'tags': '连衣裙,半身裙',\n",
      "             'tdate': '2017-08-11',\n",
      "             'type': 'jpeg',\n",
      "             'url': 'https://scontent-hkg3-1.cdninstagram.com/t51.2885-15/e35/17881057_722519881252369_3750468376053415936_n.jpg',\n",
      "             'width': '1080'},\n",
      " '_type': 'image',\n",
      " 'int_id': 14460861856687057,\n",
      " 'vector': b'\\xe1\\xa8\\x87=\\x17v\\xd7=\\x88\\xf6;\\xbc%\\t\\xe5=\\xeb\\xbe\\x9c\\xbd'\n",
      "           b'\\xacU\\xc5\\xbd\\xf9|\\x1c=!<\\x18=`\\xf3\\xd8:\\xb6\\xa0\\xcf=W\\x84\\x03;'\n",
      "           b'\\xb5]\\x8d\\xbdP&\\xd4=\\x9fnm=\\xa6([\\xbd\\x16\\xb9\\xa6=\\x89\\x9e\\x91\\xbd'\n",
      "           b'\\x82\\xfb[=\\xf2\\x1e\\x97=\\xe6&\\xe0<\\x89\\xfd\\xc1=\\x95\\x04\\xb9\\xbd'\n",
      "           b'C\\x8f=\\xbeg{\\xa6=\\xf7\\xac7\\xbe\\xd9\\x91\\xe5=\\xd4\\x90\\x89=\\tO\\xec='\n",
      "           b'\\x14,\\xd8\\xbb64\\x95\\xbd,\\x8b\\xe9\\xbdE\\x9a\\x9d=;\\x1cY\\xbd'\n",
      "           b'\\x0fu\\xb7\\xbbd\\xc9\\xa3=\\xf0J^\\xbdCq\\xa5=r$\\xc1\\xbc\\x8e\\x8e\\x1b='\n",
      "           b'1[\\xb2<\\xbc\\xfb\\xaf<\\x98\\xf2\\x9c=x)%=\\xf6\\x0c\\x9f<[D\\xa3='\n",
      "           b'\\xd5\\xbf\\xe6<\\xd1\\xc2\\x00\\xbe\\xfd\\xca\\x89=nR~\\xbd\\xf5\\xfb?\\xbb'\n",
      "           b'\\x7f\\x8c\\x85\\xbccY\\xe1<\\r\\r\\x01\\xbe\\xc1wB=\\x0f\\xfe\\x8b=g\\xd9\\xc8<'\n",
      "           b'\\x81E\\x8e=\\xc2\\xc1e\\xbd\\x0b\\\\\\xa9=$\\x99\\xd7\\xbd\\xd2\\xed\\x0e\\xbe'\n",
      "           b'@\\x95\\xdc<\\xd6\\xb7\\xd7=WrK\\xbc\\x94\\xa1\\n=\\xb1T\\xa9\\xbc\\x95\\xedT<'\n",
      "           b'\\x8c\\xaf\\x9b\\xbd\\x9bE\\x07\\xbeu\\xe3\\x9d\\xbd\\x80\\x04X\\xbc\\x03l\\xd3='\n",
      "           b'N\\xe5\\xb1\\xbd\\xbb\\xd6\\xc3=+\\x1e\\xc8\\xbb\\xc6\\x16\\x1c>'\n",
      "           b\"\\xd4\\x93\\xb2\\xbds\\xddI=|\\xd7\\x1a>\\xc1\\xdb\\x02\\xbe7\\n'=\"\n",
      "           b'\\xe7\\x1b\\xdf<=2C=b`\\x10\\xbeup-\\xbe\\x91\\xb89>\\x17K\\xf1\\xbd'\n",
      "           b'\\xaf\\xb1\\xbb=7\\x954\\xbdfy\\x0b\\xbe\\x8d\\xf4U>\\x85\\xed\\xa6=\\x9a>\\xd0<'\n",
      "           b'\\x94\\xfc\\xb3\\xbd\\r\\\\\\x80=\\x030A>\\x81Qk\\xbdt~\\xb3\\xbd\\xfaXm='\n",
      "           b'\\xdc/}\\xbdG\\x86\\x07=\\xcb\\x81J>T\\xf9\\x8f\\xbd\\x99\\x9e\\xbf\\xbdl=\\x83='\n",
      "           b'\\xc7\\xfb\\x83\\xbd\\x84G&\\xbeB\\x03\\xac=\\xdd\\x91\\xc3<dI\\x90\\xbd'\n",
      "           b'\\xb9\\xeb\\xaa=\\xa0w\\x9b\\xbc\\x97\\xb9\\x86\\xbc\\xadR\"\\xbe\\xeb/\\x94;'\n",
      "           b'\\xd9\\xa8\\xee<A\\xa3\\xd7=\\xfcy\\x83>zXQ=\\x0f\\xd0R=v\\xa03\\xbd'\n",
      "           b'\\xa8\\xb5\\x90\\xbc\\xc3J\\xa3\\xbc6h\\x95=\\x1a\\xd2\\xae<R\\xbe\\xb2=\\xf00q='\n",
      "           b'\\xd3\\x81\\xfe\\xbc'}\n"
     ]
    }
   ],
   "source": [
    "cursor = image_nn.find()\n",
    "for item in cursor:\n",
    "    pprint(item)\n",
    "    break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "batch_size=5\n",
    "cursor = nn_prod.find({},{'vector':0},batch_size=batch_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "@asyncio.coroutine\n",
    "def download(url,fobj):\n",
    "    connect = asyncio.open_connection(url,80)\n",
    "    reader,writer = yield from connect\n",
    "    header = 'GET / HTTP/1.0\\r\\nHost: %s\\r\\n\\r\\n' % host\n",
    "    writer.write(header.encode('utf-8'))\n",
    "    yield from writer.drain()\n",
    "    content = yield from reader.content\n",
    "    fobj.write(content)\n",
    "    writer.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "Cannot close a running event loop",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-43-e366996b9b79>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      1\u001b[0m \u001b[1;31m#loop = asyncio.get_event_loop()\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 2\u001b[1;33m \u001b[0mloop\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclose\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[1;32mc:\\program files\\python36\\lib\\asyncio\\selector_events.py\u001b[0m in \u001b[0;36mclose\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    105\u001b[0m     \u001b[1;32mdef\u001b[0m \u001b[0mclose\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    106\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mis_running\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 107\u001b[1;33m             \u001b[1;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m\"Cannot close a running event loop\"\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    108\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mis_closed\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    109\u001b[0m             \u001b[1;32mreturn\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mRuntimeError\u001b[0m: Cannot close a running event loop"
     ]
    }
   ],
   "source": [
    "#loop = asyncio.get_event_loop()\n",
    "loop.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {
    "collapsed": true
   },
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "This event loop is already running",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-41-6b0261fb00a2>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m      8\u001b[0m         \u001b[0mloop\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0masyncio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_event_loop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      9\u001b[0m         \u001b[0mtasks\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mdownload\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0murl\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mobj\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0murl\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mobj\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mzip\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0murl_list\u001b[0m\u001b[1;33m,\u001b[0m\u001b[0mfobject_list\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 10\u001b[1;33m         \u001b[0mloop\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun_until_complete\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0masyncio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtasks\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     11\u001b[0m         \u001b[0mloop\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclose\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     12\u001b[0m         \u001b[1;32mbreak\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mc:\\program files\\python36\\lib\\asyncio\\base_events.py\u001b[0m in \u001b[0;36mrun_until_complete\u001b[1;34m(self, future)\u001b[0m\n\u001b[0;32m    453\u001b[0m         \u001b[0mfuture\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0madd_done_callback\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0m_run_until_complete_cb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    454\u001b[0m         \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 455\u001b[1;33m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun_forever\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    456\u001b[0m         \u001b[1;32mexcept\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    457\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[0mnew_task\u001b[0m \u001b[1;32mand\u001b[0m \u001b[0mfuture\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdone\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mand\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mfuture\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcancelled\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mc:\\program files\\python36\\lib\\asyncio\\base_events.py\u001b[0m in \u001b[0;36mrun_forever\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    407\u001b[0m         \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_check_closed\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    408\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mis_running\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 409\u001b[1;33m             \u001b[1;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'This event loop is already running'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    410\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mevents\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_running_loop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    411\u001b[0m             raise RuntimeError(\n",
      "\u001b[1;31mRuntimeError\u001b[0m: This event loop is already running"
     ]
    }
   ],
   "source": [
    "item_list = []\n",
    "url_list = []\n",
    "\n",
    "for item in cursor:\n",
    "    if len(url_list)==5:\n",
    "        #store and download and then insert\n",
    "        fobject_list = [BytesIO() for _ in range(batch_size)]\n",
    "        loop = asyncio.get_event_loop()\n",
    "        tasks = [download(url,obj) for url,obj in zip(url_list,fobject_list)]\n",
    "        loop.run_until_complete(asyncio.wait(tasks))\n",
    "        loop.close()\n",
    "        break\n",
    "    item_list.append(item)\n",
    "    url_list.append(item['_source']['cdn_url'])\n",
    "    "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "['https://cdn.aidigger.com/images/instagram/e2452f9daaad3ef7070adb22ee70958a.jpeg',\n",
       " 'https://cdn.aidigger.com/images/instagram/bd717eaa4c351b842a497e8907b69855.jpeg',\n",
       " 'https://cdn.aidigger.com/images/instagram/189a2af5d9661500b32271ca9b1865be.jpeg',\n",
       " 'https://cdn.aidigger.com/images/instagram/6e70c94dd3fac214c5d7e6c061df2b2f.jpeg',\n",
       " 'https://cdn.aidigger.com/images/instagram/f95f00da22a2e143e6e457b10544a120.jpeg']"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "url_list"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "ret = requests.get(img_url)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "f= BytesIO()\n",
    "f.write(ret.content)\n",
    "img_io = Image.open(f)\n",
    "np_img = np.asarray(img_io)\n",
    "md_img = nd.array(np_img)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "This event loop is already running",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mRuntimeError\u001b[0m                              Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-45-0e2937f1f084>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m     19\u001b[0m \u001b[0mloop\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0masyncio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mget_event_loop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m     20\u001b[0m \u001b[0mtasks\u001b[0m \u001b[1;33m=\u001b[0m \u001b[1;33m[\u001b[0m\u001b[0mwget\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mhost\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mhost\u001b[0m \u001b[1;32min\u001b[0m \u001b[1;33m[\u001b[0m\u001b[1;34m'www.sina.com.cn'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'www.sohu.com'\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'www.163.com'\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m]\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 21\u001b[1;33m \u001b[0mloop\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun_until_complete\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0masyncio\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mwait\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mtasks\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m     22\u001b[0m \u001b[0mloop\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mclose\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mc:\\program files\\python36\\lib\\asyncio\\base_events.py\u001b[0m in \u001b[0;36mrun_until_complete\u001b[1;34m(self, future)\u001b[0m\n\u001b[0;32m    453\u001b[0m         \u001b[0mfuture\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0madd_done_callback\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0m_run_until_complete_cb\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    454\u001b[0m         \u001b[1;32mtry\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 455\u001b[1;33m             \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mrun_forever\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    456\u001b[0m         \u001b[1;32mexcept\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    457\u001b[0m             \u001b[1;32mif\u001b[0m \u001b[0mnew_task\u001b[0m \u001b[1;32mand\u001b[0m \u001b[0mfuture\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdone\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mand\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[0mfuture\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcancelled\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32mc:\\program files\\python36\\lib\\asyncio\\base_events.py\u001b[0m in \u001b[0;36mrun_forever\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m    407\u001b[0m         \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_check_closed\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    408\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mis_running\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 409\u001b[1;33m             \u001b[1;32mraise\u001b[0m \u001b[0mRuntimeError\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'This event loop is already running'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m    410\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mevents\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0m_get_running_loop\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mis\u001b[0m \u001b[1;32mnot\u001b[0m \u001b[1;32mNone\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    411\u001b[0m             raise RuntimeError(\n",
      "\u001b[1;31mRuntimeError\u001b[0m: This event loop is already running"
     ]
    }
   ],
   "source": [
    "\n",
    "@asyncio.coroutine\n",
    "def wget(host):\n",
    "    print('wget %s...' % host)\n",
    "    connect = asyncio.open_connection(host, 80)\n",
    "    reader, writer = yield from connect\n",
    "    header = 'GET / HTTP/1.0\\r\\nHost: %s\\r\\n\\r\\n' % host\n",
    "    writer.write(header.encode('utf-8'))\n",
    "    yield from writer.drain()\n",
    "    while True:\n",
    "        line = yield from reader.readline()\n",
    "        if line == b'\\r\\n':\n",
    "            break\n",
    "\n",
    "        print('%s header > %s' % (host, line.decode('utf-8').rstrip()))\n",
    "    # Ignore the body, close the socket\n",
    "    writer.close()\n",
    "\n",
    "loop = asyncio.get_event_loop()\n",
    "tasks = [wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']]\n",
    "loop.run_until_complete(asyncio.wait(tasks))\n",
    "loop.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
